﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

/// <summary>
/// 集合助手类 支持数组/List/可foreach的集合 的类型
/// 提供了以Ex开头的扩展方法
/// </summary>
public static class ListHelper
{
    /// <summary>
    /// 找 数组/List 最大值
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <typeparam name="Tvalue">从元素上取出来的指标 的类型</typeparam>
    /// <param name="list">数组/集合</param>
    /// <param name="GetValue">委托,由调用者传进来方法,用来取指标</param>
    /// <returns></returns>
    public static T Max<T, Tvalue>(this IList<T> list, Func<T, Tvalue> GetValue) where Tvalue : IComparable<Tvalue>
    {
        T max = list[0];

        for (int i = 1; i < list.Count; i++)
        {
            if (GetValue(list[i]).CompareTo(GetValue(max)) > 0)
            {
                max = list[i];
            }
        }
        return max;
    }

    /// <summary>
    /// 找 数组/List 最大值
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <typeparam name="Tvalue">从元素上取出来的指标 的类型</typeparam>
    /// <param name="list">数组/集合</param>
    /// <param name="GetValue">委托,由调用者传进来方法,用来取指标</param>
    /// <returns></returns>
    public static T Max<T, Tvalue>(this ICollection<T> list, Func<T, Tvalue> GetValue) where Tvalue : IComparable<Tvalue>
    {
        //假设最开始的是最大的
        var enu = list.GetEnumerator();
        enu.MoveNext();
        T max = enu.Current;

        while (enu.MoveNext())
        {
            if (GetValue(enu.Current).CompareTo(GetValue(max)) > 0)
            {
                max = enu.Current;
            }
        }
        return max;
    }

    /// <summary>
    /// 找 数组/List 最大值
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <typeparam name="Tvalue">从元素上取出来的指标 的类型</typeparam>
    /// <param name="list">数组/集合</param>
    /// <param name="GetValue">委托,由调用者传进来方法,用来取指标</param>
    /// <returns></returns>
    public static T Max<T, Tvalue>(this IEnumerable list, Func<T, Tvalue> GetValue) where Tvalue : IComparable<Tvalue>
    {
        //假设最开始的是最大的
        var enu = list.GetEnumerator();
        enu.MoveNext();
        T max = (T)enu.Current;

        while (enu.MoveNext())
        {
            if (GetValue((T)enu.Current).CompareTo(GetValue(max)) > 0)
            {
                max = (T)enu.Current;
            }
        }
        return max;
    }

    /// <summary>
    /// 找 数组/List 最小值
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <typeparam name="Tvalue">从元素上取出来的指标 的类型</typeparam>
    /// <param name="list">数组/集合</param>
    /// <param name="GetValue">委托,由调用者传进来方法,用来取指标</param>
    /// <returns></returns>
    public static T Min<T, Tvalue>(this IList<T> list, Func<T, Tvalue> GetValue) where Tvalue : IComparable<Tvalue>
    {
        //假设第0个是最小的
        T min = list[0];
        for (int i = 1; i < list.Count; i++)
        {
            if (GetValue(list[i]).CompareTo(GetValue(min)) < 0)
            {
                min = list[i];
            }
        }
        return min;
    }

    /// <summary>
    /// 找 数组/List 最小值
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <typeparam name="Tvalue">从元素上取出来的指标 的类型</typeparam>
    /// <param name="list">数组/集合</param>
    /// <param name="GetValue">委托,由调用者传进来方法,用来取指标</param>
    /// <returns></returns>
    public static T Min<T, Tvalue>(this ICollection<T> list, Func<T, Tvalue> GetValue) where Tvalue : IComparable<Tvalue>
    {
        //假设最开始的是最小的
        var enu = list.GetEnumerator();
        enu.MoveNext();
        T min = enu.Current;

        while (enu.MoveNext())
        {
            if (GetValue(enu.Current).CompareTo(GetValue(min)) < 0)
            {
                min = enu.Current;
            }
        }
        return min;
    }

    /// <summary>
    /// 找 数组/List 最小值
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <typeparam name="Tvalue">从元素上取出来的指标 的类型</typeparam>
    /// <param name="list">数组/集合</param>
    /// <param name="GetValue">委托,由调用者传进来方法,用来取指标</param>
    /// <returns></returns>
    public static T Min<T, Tvalue>(this IEnumerable list, Func<T, Tvalue> GetValue) where Tvalue : IComparable<Tvalue>
    {
        //假设最开始的是最小的
        var enu = list.GetEnumerator();
        enu.MoveNext();
        T min = (T)enu.Current;

        while (enu.MoveNext())
        {
            if (GetValue((T)enu.Current).CompareTo(GetValue(min)) < 0)
            {
                min = (T)enu.Current;
            }
        }
        return min;
    }

    /// <summary>
    /// 找符合条件的一个元素
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <param name="list">数组/List</param>
    /// <param name="condition">条件</param>
    /// <param name="result">输出结果</param>
    /// <returns>返回值表示有没有找到</returns>
    public static bool Find<T>(this IList<T> list, Func<T, bool> condition, out T result)
    {
        for (int i = 0; i < list.Count; i++)
        {
            if (condition(list[i]))
            {
                result = list[i];
                return true;
            }
        }
        result = default(T);
        return false;
    }

    /// <summary>
    /// 找符合条件的一个元素
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <param name="list">数组/List</param>
    /// <param name="condition">条件</param>
    /// <param name="result">输出结果</param>
    /// <returns>返回值表示有没有找到</returns>
    public static bool Find<T>(this ICollection<T> list, Func<T, bool> condition, out T result)
    {
        foreach (var item in list)
        {
            if (condition(item))
            {
                result = item;
                return true;
            }
        }
        result = default(T);
        return false;
    }

    /// <summary>
    /// 找符合条件的一个元素
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <param name="list">数组/List</param>
    /// <param name="condition">条件</param>
    /// <param name="result">输出结果</param>
    /// <returns>返回值表示有没有找到</returns>
    public static bool Find<T>(this IEnumerable list, Func<T, bool> condition, out T result)
    {
        foreach (var item in list)
        {
            if (condition((T)item))
            {
                result = (T)item;
                return true;
            }
        }
        result = default(T);
        return false;
    }

    /// <summary>
    /// 找符合条件的多个元素
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <param name="list">数组/List</param>
    /// <param name="condition">条件</param>
    /// <param name="result">由外部传入一个List用来接收找到的结果,这个List可以复用,NoGC</param>
    /// <returns>返回值表示有没有找到</returns>
    public static bool FindAll<T>(this IList<T> list, Func<T, bool> condition, List<T> result)
    {
        if (result.Count > 0) result.Clear();
        for (int i = 0; i < list.Count; i++)
        {
            if (condition(list[i]))
            {
                result.Add(list[i]);
            }
        }
        return result.Count > 0 ? true : false;
    }

    /// <summary>
    /// 找符合条件的多个元素
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <param name="list">数组/List</param>
    /// <param name="condition">条件</param>
    /// <param name="result">由外部传入一个List用来接收找到的结果,这个List可以复用,NoGC</param>
    /// <returns>返回值表示有没有找到</returns>
    public static bool FindAll<T>(this ICollection<T> list, Func<T, bool> condition, List<T> result)
    {
        if (result.Count > 0) result.Clear();
        foreach (var item in list)
        {
            if (condition(item))
            {
                result.Add(item);
            }
        }
        return result.Count > 0 ? true : false;
    }

    /// <summary>
    /// 找符合条件的多个元素 不会递归查找
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <param name="list">数组/List</param>
    /// <param name="condition">条件</param>
    /// <param name="result">由外部传入一个List用来接收找到的结果,这个List可以复用,NoGC</param>
    /// <returns>返回值表示有没有找到</returns>
    public static bool FindAll<T>(this IEnumerable<T> list, Func<T, bool> condition, List<T> result)
    {
        if (result.Count > 0) result.Clear();
        foreach (var item in list)
        {
            if (condition(item))
            {
                result.Add(item);
            }
        }
        return result.Count > 0 ? true : false;
    }

    /// <summary>
    /// 找符合条件的多个元素,不会递归查找
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <param name="list">数组/List</param>
    /// <param name="condition">条件</param>
    /// <param name="result">由外部传入一个List用来接收找到的结果,这个List可以复用,NoGC</param>
    /// <returns>返回值表示有没有找到</returns>
    public static bool FindAll<T>(this IEnumerable list, Func<T, bool> condition, List<T> result)
    {
        if (result.Count > 0) result.Clear();
        foreach (var item in list)
        {
            if (condition((T)item))
            {
                result.Add((T)item);
            }
        }
        return result.Count > 0 ? true : false;
    }

    /// <summary>
    /// 求同一指标的累加和
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <param name="list">数组/List</param>
    /// <param name="GetValue">委托,由调用者传进来方法,用来取指标</param>
    /// <returns>累加和 double类型</returns>
    public static double Sum<T>(this IList<T> list, Func<T, double> GetValue)
    {
        double sum = 0;
        for (int i = 0; i < list.Count; i++)
        {
            sum += GetValue(list[i]);
        }
        return sum;
    }

    /// <summary>
    /// 求同一指标的累加和
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <param name="list">数组/List</param>
    /// <param name="GetValue">委托,由调用者传进来方法,用来取指标</param>
    /// <returns>累加和 double类型</returns>
    public static double Sum<T>(this ICollection<T> list, Func<T, double> GetValue)
    {
        double sum = 0;
        foreach (var item in list)
        {
            sum += GetValue(item);
        }
        return sum;
    }

    /// <summary>
    /// 求同一指标的平均值
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <param name="list">数组/List</param>
    /// <param name="GetValue">委托,由调用者传进来方法,用来取指标</param>
    /// <returns>平均值 double类型</returns>
    public static double Avg<T>(this IList<T> list, Func<T, double> GetValue)
    {
        return Sum(list, GetValue) / list.Count;
    }

    /// <summary>
    /// 求同一指标的平均值
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <param name="list">数组/List</param>
    /// <param name="GetValue">委托,由调用者传进来方法,用来取指标</param>
    /// <returns>平均值 double类型</returns>
    public static double Avg<T>(this ICollection<T> list, Func<T, double> GetValue)
    {
        return Sum(list, GetValue) / list.Count;
    }

    /// <summary>
    /// 操作集合中的所有的元素
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <param name="list">数组/List</param>
    /// <param name="action">操作元素的委托</param>
    public static void EveryOne<T>(this IList<T> list, Action<T> action)
    {
        for (int i = 0; i < list.Count; i++)
        {
            action(list[i]);
        }
    }

    /// <summary>
    /// 操作集合中的所有的元素
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <param name="list">数组/List</param>
    /// <param name="action">操作元素的委托</param>
    public static void EveryOne<T>(this ICollection<T> list, Action<T> action)
    {
        foreach (var item in list)
        {
            action(item);
        }
    }

    /// <summary>
    /// 单条件排序
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <typeparam name="Tvalue">从元素上取出来的指标 的类型</typeparam>
    /// <param name="list">数组/集合</param>
    /// <param name="GetValue">委托,由调用者传进来方法,用来取指标</param>
    public static void Sort<T, Tvalue>(this IList<T> list, Func<T, Tvalue> GetValue) where Tvalue : IComparable<Tvalue>
    {
        for (int j = 0; j < list.Count - 1; j++)//i表示开始选择的位置
        {
            int mIndex = j;//假设开头的是最小的    存位置
            for (int i = j + 1; i < list.Count; i++)
            {
                if (GetValue(list[i]).CompareTo(GetValue(list[mIndex])) < 0)
                {
                    mIndex = i;
                }
            }
            //交换
            T temp = list[mIndex];//把最小的备份一下
            list[mIndex] = list[j];//最小的位置装开头的
            list[j] = temp;//开头的装最小的
        }
    }

    /// <summary>
    /// 找符合条件的多个元素
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <param name="list">数组/List</param>
    /// <param name="condition">条件</param>
    /// <returns>返回值表示是否包含</returns>
    public static bool Contains<T>(this IList<T> list, Func<T, bool> condition)
    {
        for (int i = 0; i < list.Count; i++)
        {
            if (condition(list[i]))
            {
                return true;
            }
        }
        return false;
    }

    /// <summary>
    /// 找符合条件的多个元素
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <param name="list">数组/List</param>
    /// <param name="condition">条件</param>
    /// <returns>返回值表示是否包含</returns>
    public static bool Contains<T>(this IEnumerable list, Func<T, bool> condition)
    {
        foreach (var item in list)
        {
            if (condition((T)item))
            {
                return true;
            }
        }
        return false;
    }

    /// <summary>
    /// 找符合条件的多个元素
    /// </summary>
    /// <typeparam name="T">数组/List/可foreach的集合 的类型</typeparam>
    /// <param name="list">数组/List</param>
    /// <param name="condition">条件</param>
    /// <returns>返回值表示是否包含</returns>
    public static bool Contains<T>(this ICollection list, Func<T, bool> condition)
    {
        foreach (var item in list)
        {
            if (condition((T)item))
            {
                return true;
            }
        }
        return false;
    }
}